import { baseUrl, requestOptions } from "../config/env";
import { delayToast, navigateTo } from "./utils";
import store from "../store/index";
const { authorizationKey, successCode, loginPageUrl, } = requestOptions
/**登录状态是否已失效 */
let loginInvalid = false
/**token失效重新请求队列 */
let reuqestQueue = []
/**重新登录中 */
let logging = false
/**
 * reuqest请求
 * @param {Object} [options] 
 * @param {String} [options.url] 接口地址
 * @param {object} [options.data] 请求的参数
 * @param {object} [options.header] 设置请求的 header
 * @param {String} [options.method] 请求方式
 * @param {Number} [options.timeout] 超时时间，单位 ms
 * @param {String} [options.responseType] 设置响应的数据类型。合法值：text、arraybuffer
 * @param {Boolean} [options.showNavigationBarLoading] 在当前页面显示导航条加载动画 默认 true
 * @param {Boolean} [options.needToken] 请求携带token 默认 true
 * @returns {Promise}
 */
function request(options) {
  const { url, data = {}, header, method = 'GET', timeout = 60000, responseType, showNavigationBarLoading = true, needToken = true } = options;

  return new Promise((resolve, reject) => {
    showNavigationBarLoading && uni.showNavigationBarLoading()
    if (!loginPageUrl && loginInvalid) {
      // 登录状态失效，存储请求
      reuqestQueue.push({ options, resolve, reject })
    } else {
      uni.request({
        url: url ? url : `${baseUrl}${url}`, //仅为示例，并非真实接口地址。
        data: data,
        header: needToken ? { ...header, ...{ [authorizationKey]: store.getters.access_token || '' } } : header,
        method: method.toUpperCase(),
        timeout,
        responseType,
        success: (res) => {
          if (responseType === 'arraybuffer') {
            resolve(res.data)
          } else {
            const { code, data } = res.data
            if (isHttpSuccess(res.statusCode) && code === successCode) {
              // 成功
              loginInvalid = false
              resolve(data)
            } else {
              if (needToken && code === 401) {
                // token失效
                console.log('token 失效');
                tokenInvalidController(res, options, resolve, reject)
              } else {
                showErr(res.data)
                reject(res.data)
              }
            }
          }
        },
        fail: err => {
          showErr(err)
          reject(err);
        },
        complete: () => {
          showNavigationBarLoading && uni.hideNavigationBarLoading()
        }
      });
    }

  })
}

/**
 * 错误提示
 * @param {any} err 错误信息
 */
function showErr(err) {
  console.log('Request Fail ', err);
  const msg = errPicker(err);
  uni.showToast({
    title: msg,
    icon: 'none'
  });
}
/**
 * 提炼错误信息
 * @param {any} err 错误信息
 */
function errPicker(err) {
  if (typeof err === 'string') {
    return err;
  }
  return err.msg || err.errMsg || err.message || err.error || (err.detail && err.detail.errMsg) || '未知错误';
}

/**
 * 判断请求状态是否成功
 * @param {Number | String} status http状态码
 * @returns {Boolean}
 */
function isHttpSuccess(status) {
  status = Number(status)
  return (status >= 200 && status < 300) || status === 304;
}

/**
 * token 失效
 */
async function tokenInvalidController(response, options, resolve, reject) {
  if (loginPageUrl) {
    // 已配置token失效重定向地址
    if (!loginInvalid) {
      // 避免多个请求失效重复跳转登录页
      loginInvalid = true
      await delayToast(errPicker(response.data))
      const pages = getCurrentPages();
      navigateTo(`${loginPageUrl}?redirectUrl=${pages[pages.length - 1].route}`)
      loginInvalid = false
    }
  } else {
    // #ifdef MP
    // uni.login登录
    reuqestQueue.push({ options, resolve, reject })
    console.log(reuqestQueue);
    loginInvalid = true
    if (!logging) {
      logging = true
      store.dispatch('LoginByCode').then(() => {
        loginInvalid = false
        logging = false
        reuqestQueue.map(item => {
          request(item.options).then(res => {
            item.resolve(res)
          }).catch(err => {
            item.reject(err)
          })
        })
        reuqestQueue = []
      }).catch((err) => {
        loginInvalid = false
        reuqestQueue.map(item => {
          item.reject(err)
        })
        reuqestQueue = []
      })
    }
    // #endif
  }

}

export default request